package com.chenyue.cm.api.match;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.chenyue.cm.auth.Login;
import com.chenyue.cm.auth.LoginUser;
import com.chenyue.cm.auth.token.LoginUserInfo;
import com.chenyue.cm.auth.token.RequestUtil;
import com.chenyue.cm.bean.Success;
import com.chenyue.cm.common.constant.ErrorCode;
import com.chenyue.cm.common.vo.Page;
import com.chenyue.cm.exception.SysRuntimeException;
import com.chenyue.cm.match.domain.*;
import com.chenyue.cm.match.service.*;
import com.chenyue.cm.match.vo.JdMatchVo;
import com.chenyue.cm.match.vo.MatchItem;
import com.chenyue.cm.match.vo.MatchScoreList;
import com.chenyue.cm.match.vo.param.ScoreParam;
import com.chenyue.cm.msg.service.PushService;
import com.chenyue.cm.user.domain.JdAppUser;
import com.chenyue.cm.utils.DateUtils;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author libingxing
 */
@Api(tags = "赛事打分")
@RestController
@RequestMapping("/api/match/score")
public class MatchScoreController {

    private final JdMatchScoreRecordService matchScoreRecordService;

    private final JdMatchLiveUserService matchLiveUserService;

    private final ViewMatchItemService viewMatchItemService;

    private final JdMatchScoreApplyService matchScoreApplyService;

    private final ViewScoreApplyService viewScoreApplyService;

    private final JdMatchFormatMemberService matchFormatMemberService;

    private final JdMatchFormatService matchFormatService;

    private final JdMatchService matchService;

    private final FormatLiveRecordService formatLiveRecordService;

    private final PushService pushService;

    public MatchScoreController(JdMatchScoreRecordService matchScoreRecordService, JdMatchLiveUserService matchLiveUserService, ViewMatchItemService viewMatchItemService, JdMatchScoreApplyService matchScoreApplyService, ViewScoreApplyService viewScoreApplyService, JdMatchFormatMemberService matchFormatMemberService, JdMatchFormatService matchFormatService, JdMatchService matchService, FormatLiveRecordService formatLiveRecordService, PushService pushService) {
        this.matchScoreRecordService = matchScoreRecordService;
        this.matchLiveUserService = matchLiveUserService;
        this.viewMatchItemService = viewMatchItemService;
        this.matchScoreApplyService = matchScoreApplyService;
        this.viewScoreApplyService = viewScoreApplyService;
        this.matchFormatMemberService = matchFormatMemberService;
        this.matchFormatService = matchFormatService;
        this.matchService = matchService;
        this.formatLiveRecordService = formatLiveRecordService;
        this.pushService = pushService;
    }

    @PostMapping("/score")
    @ApiOperation(value = "赛事打分", notes = "赛事打分")
    @ApiOperationSupport(order = 10)
    @Transactional(rollbackFor = Exception.class)
    public Success<String> score(
            @ApiParam @RequestBody ScoreParam param,
            HttpServletRequest request
    ) {
        JdAppUser user = new JdAppUser();
        try {
            final LoginUserInfo userInfo = RequestUtil.getUserInfoByRequest(request);
            user.setId(userInfo.getUserId());
        } catch (Exception ignored) {
            user.setId(param.getUserId());
        }
        for (ScoreParam.ScoreInfo scoreInfo : param.getScoreInfoList()) {
            JdMatchScoreRecord record = matchScoreRecordService.lambdaQuery()
                    .eq(JdMatchScoreRecord::getFormatId, param.getFormatId())
                    .eq(JdMatchScoreRecord::getUserId, scoreInfo.getUserId())
                    .eq(JdMatchScoreRecord::getJudgeId, user.getId())
                    .eq(JdMatchScoreRecord::getItemId, param.getItemId())
                    .last(" limit 1 ").one();
            boolean flag;
            if (record != null) {
                record.setScore(scoreInfo.getScore());
                record.setCt(DateUtils.getToday());
                flag = matchScoreRecordService.updateById(record);
            } else {
                record = new JdMatchScoreRecord();
                record.setGroupId(scoreInfo.getGroupId());
                record.setFormatId(param.getFormatId());
                record.setItemId(param.getItemId());
                record.setUserId(scoreInfo.getUserId());
                record.setJudgeId(Integer.valueOf(user.getId()));
                record.setScore(scoreInfo.getScore());
                record.setCt(Calendar.getInstance().getTime());
                flag = matchScoreRecordService.save(record);
            }
            if (!flag) {
                throw new SysRuntimeException(ErrorCode.INSERT_ERROR.getMsg());
            } else {
//                打分记录总数
                int scoreCount = matchScoreRecordService.lambdaQuery()
                        .eq(JdMatchScoreRecord::getFormatId, param.getFormatId())
                        .count();
//                参赛成员总数
                int memberCount = matchLiveUserService.lambdaQuery()
                        .eq(JdMatchLiveUser::getFormatId, param.getFormatId())
                        .count();
//                赛事项目数量
                final JdMatchFormat matchFormat = matchFormatService.getById(param.getFormatId());
                final ViewMatchItem matchItem = viewMatchItemService.getById(matchFormat.getMatchId());
                final String[] itemIds = matchItem.getItemIds().split(",");
                boolean isFinish;
                if (itemIds.length > 1) {
//                    多项
                    isFinish = scoreCount == (memberCount * itemIds.length);
                } else {
//                    单项
                    isFinish = scoreCount == memberCount;
                }
                if (isFinish) {
//                    打分已经完成
                    System.err.println("=======进入分数核算阶段========");
                    List<JdMatchFormatMember> promotionList = matchLiveUserService.calculateAndRank(matchFormat);
                    if (promotionList == null || promotionList.size() == 0) {
                        return Success.success("打分完成，请手动晋级", "");
                    }
                    if (matchFormat.getArrangeOrder() < 3) {
                        for (JdMatchFormatMember formatMember : promotionList) {
                            matchService.enterNextFormat(2, matchFormat.getMatchId(), formatMember.getUserId(), formatMember.getGroupId());
                            pushService.enterFormatPush(formatMember);
                        }
                    }
                }
            }
        }
        return Success.success();
    }

    @GetMapping("/itemList")
    @ApiOperation(value = "赛事项目列表", notes = "赛事项目列表")
    @ApiOperationSupport(order = 11)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "integer", required = true),
    })
    public Success<List<MatchItem>> itemList(
            Integer matchId
    ) {
        List<MatchItem> list;
        try {
            final ViewMatchItem one = viewMatchItemService.getOne(
                    new QueryWrapper<ViewMatchItem>()
                            .lambda()
                            .eq(ViewMatchItem::getId, matchId)
                            .last(" limit 1")
            );
            final String[] itemArray = one.getItemNames().split(",");
            final String[] itemIdArray = one.getItemIds().split(",");
            list = new ArrayList<>(itemArray.length);
            for (int i = 0; i < itemArray.length; i++) {
                MatchItem matchItem = new MatchItem();
                matchItem.setItemId(itemIdArray[i]);
                matchItem.setItemName(itemArray[i]);
                list.add(matchItem);
            }
        } catch (Exception e) {
            return Success.error("赛事项目设置异常");
        }
        return Success.success(list);
    }

    @GetMapping("/scoreList")
    @ApiOperation(value = "赛事项目打分详情", notes = "赛事项目打分详情")
    @ApiOperationSupport(order = 12)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "项目id", name = "itemId", dataType = "integer", required = true),
            @ApiImplicitParam(value = "直播记录id", name = "recordId", dataType = "integer", required = true),
            @ApiImplicitParam(value = "赛事类型 1单人/2团队", name = "matchType", dataType = "integer", required = true),
            @ApiImplicitParam(value = "当前页", name = "page", dataType = "int", required = true),
            @ApiImplicitParam(value = "条数", name = "rows", dataType = "int", required = true),
    })
    @Transactional(rollbackFor = Exception.class)
    public Success<MatchScoreList> scoreList(
            Integer itemId, Integer recordId, Integer matchType,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "20") Integer rows
    ) {
        final MatchScoreList scoreList = new MatchScoreList();
        if (matchType == 1) {
//            单人
            int total = matchLiveUserService.matchMemberScoreListCount(recordId, itemId, 0);
            final Page<List<MatchScoreList.MatchMemberList>> memberScoreListPage = new Page<>(page, rows, total);
            List<MatchScoreList.MatchMemberList> memberScoreList = matchLiveUserService.matchMemberScoreList(recordId, itemId, 0, memberScoreListPage.convertPage());
            memberScoreListPage.setContent(memberScoreList);
            scoreList.setMemberScoreListPage(memberScoreListPage);
        } else {
//            团队
            int total = matchLiveUserService.matchGroupScoreListCount(recordId, itemId);
            final Page<List<MatchScoreList.MatchGroupList>> memberScoreListPage = new Page<>(page, rows, total);
            List<MatchScoreList.MatchGroupList> groupList = matchLiveUserService.matchGroupScoreList(recordId, itemId, memberScoreListPage.convertPage());
            for (MatchScoreList.MatchGroupList group : groupList) {
//                查询团队-成员成绩
                List<MatchScoreList.MatchMemberList> memberScoreList = matchLiveUserService.matchMemberScoreList(recordId, itemId, group.getGroupId(), memberScoreListPage.convertPage());
                group.setMemberScoreList(memberScoreList);
            }
            memberScoreListPage.setContent(groupList);
            scoreList.setMatchGroupListPage(memberScoreListPage);
        }

        return Success.success(scoreList);
    }

    @GetMapping("/handlePromotionList")
    @ApiOperation("手动晋级列表")
    @ApiOperationSupport(order = 12)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "项目id", name = "itemId", dataType = "integer", required = true),
            @ApiImplicitParam(value = "赛程id", name = "formatId", dataType = "string", required = true),
            @ApiImplicitParam(value = "赛事类型 1单人/2团队", name = "matchType", dataType = "integer", required = true),
    })
    @Transactional(rollbackFor = Exception.class)
    public Success<MatchScoreList> handlePromotionList(
            Integer itemId, String formatId, Integer matchType
    ) {
        final MatchScoreList scoreList = new MatchScoreList();
        if (matchType == 1) {
//            单人
            List<MatchScoreList.MatchMemberList> memberScoreList = matchLiveUserService.matchMemberScoreList(formatId, itemId, 0);
            scoreList.setMemberScoreList(memberScoreList);
        } else {
//            团队
            List<MatchScoreList.MatchGroupList> groupList = matchLiveUserService.matchGroupScoreList(formatId, itemId);
            List<MatchScoreList.MatchGroupList> result = new ArrayList<>(groupList.size());
            for (MatchScoreList.MatchGroupList group : groupList) {
//                查询团队-成员成绩
                List<MatchScoreList.MatchMemberList> memberScoreList = matchLiveUserService.matchMemberScoreList(formatId, itemId, group.getGroupId());
                group.setMemberScoreList(memberScoreList);

                result.add(group);
            }
            scoreList.setMatchGroupList(result);
        }

        return Success.success(scoreList);
    }

    @Login
    @PostMapping("/scoreApplyList")
    @ApiOperation("打分记录申诉列表")
    @Transactional(rollbackFor = Exception.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "当前页", name = "page", dataType = "int", required = true),
            @ApiImplicitParam(value = "条数", name = "rows", dataType = "int", required = true),
    })
    public Success<Page<List<ViewScoreApply>>> scoreApplyList(
            @ApiIgnore @LoginUser JdAppUser user,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer rows
    ) {
//        先查询该裁判进行中的赛事
        final List<FormatLiveRecord> formatList = formatLiveRecordService.lambdaQuery()
                .lt(FormatLiveRecord::getMatchStartTime, DateUtils.getToday())
                .gt(FormatLiveRecord::getMatchEndTime, DateUtils.getToday())
                .eq(FormatLiveRecord::getUserId, user.getId())
                .list();
        Page<List<ViewScoreApply>> result = new Page<>(page, rows, 0);
        result.setContent(new ArrayList<>());
        if (formatList.size() == 0) {
            return Success.success(result);
        }
        final List<Integer> formatIdList = formatList.stream().map(FormatLiveRecord::getArrangeId).collect(Collectors.toList());
//        查询这些赛事是否有待审核的申诉
        final LambdaQueryChainWrapper<ViewScoreApply> eq = viewScoreApplyService.lambdaQuery()
                .in(ViewScoreApply::getFormatId, formatIdList)
                .eq(ViewScoreApply::getCheckState, 0);
        final Integer total = eq.count();
        result = new Page<>(page, rows, total);
        final List<ViewScoreApply> list = eq.list();
        result.setContent(list);
        return Success.success(result);
    }

    @Login
    @PostMapping("/scoreApply")
    @ApiOperation("打分记录申诉")
    @ApiOperationSupport(order = 1)
    @Transactional(rollbackFor = Exception.class)
    public Success<String> scoreApply(
            @ApiIgnore @LoginUser JdAppUser user,
            @ApiParam @RequestBody JdMatchScoreApply apply
    ) {
        final JdMatchScoreApply one = matchScoreApplyService.lambdaQuery()
                .eq(JdMatchScoreApply::getUserId, user.getId())
                .eq(JdMatchScoreApply::getScoreRecordId, apply.getScoreRecordId())
                .last("limit 1")
                .one();
        if (one != null) {
            return Success.error("您已经申诉过了，请勿重复申诉！");
        }
        apply.setUserId(Integer.valueOf(user.getId()));
        apply.setCt(DateUtils.getToday());
        final boolean save = matchScoreApplyService.save(apply);
        return save ? Success.success() : Success.error(ErrorCode.INSERT_ERROR.getMsg());
    }

    @Login
    @PostMapping("/scoreApplyCheck")
    @ApiOperation("打分记录申诉处理")
    @ApiOperationSupport(order = 1)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "申诉记录id", name = "applyId", dataType = "integer", required = true),
            @ApiImplicitParam(value = "申诉处理 1通过2拒绝", name = "checkState", dataType = "integer", required = true),
            @ApiImplicitParam(value = "拒绝理由", name = "refuseResult", dataType = "String", required = true),
            @ApiImplicitParam(value = "要修改的成绩", name = "score", dataType = "integer", required = true)
    })
    @Transactional(rollbackFor = Exception.class)
    public Success<String> scoreApplyCheck(
            @ApiIgnore @LoginUser JdAppUser user,
            Integer applyId,
            Integer checkState, String refuseResult,
            Integer score
    ) {
        final JdMatchScoreApply one = matchScoreApplyService.lambdaQuery()
                .eq(JdMatchScoreApply::getId, applyId)
                .last("limit 1")
                .one();
        if (one == null || one.getCheckState() > 0) {
            return Success.error("记录不存在或已处理");
        }
        one.setCheckState(checkState);
        one.setRefuseResult(refuseResult);
        one.setEu(user.getId() + "");
        one.setEt(Calendar.getInstance().getTime());
        if (checkState == 1) {
            final JdMatchScoreRecord scoreRecord = matchScoreRecordService.lambdaQuery().eq(JdMatchScoreRecord::getId, one.getScoreRecordId()).last("limit 1").one();
            final JdMatchFormatMember formatMember = matchFormatMemberService.lambdaQuery()
                    .eq(JdMatchFormatMember::getFormatId, scoreRecord.getFormatId())
                    .eq(JdMatchFormatMember::getUserId, scoreRecord.getUserId())
                    .one();
            if (formatMember == null) {
                return Success.error("成绩异常，无法修改");
            }
            formatMember.setScore(formatMember.getScore() - scoreRecord.getScore() + score);
            scoreRecord.setScore(score);
            final boolean success = matchFormatMemberService.updateById(formatMember);
            if (!success) {
                throw new SysRuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
            }
            final int flag = matchScoreRecordService.updateByPrimaryKey(scoreRecord);
            if (flag == 0) {
                throw new SysRuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
            }
        }
        final int i = matchScoreApplyService.updateByPrimaryKey(one);
        if (i == 0) {
            throw new SysRuntimeException(ErrorCode.UPDATE_ERROR.getMsg());
        }
        return Success.success();
    }

    @Login
    @PostMapping("/handlePromotion")
    @ApiOperation("手动晋级")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "用户id", name = "userId", dataType = "integer", required = true),
            @ApiImplicitParam(value = "赛程id", name = "formatId", dataType = "integer", required = true),
            @ApiImplicitParam(value = "1晋级2淘汰", name = "state", dataType = "integer", required = true),
            @ApiImplicitParam(value = "当前赛程阶段 1初2复3决", name = "arrangeOrder", dataType = "integer", required = true),
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "integer", required = true),
    })
    public Success<String> handlePromotion(
            Integer userId, Integer formatId, Integer state, Integer arrangeOrder, Integer matchId
    ) {
        final JdMatchFormatMember one = matchFormatMemberService.lambdaQuery()
                .eq(JdMatchFormatMember::getUserId, userId)
                .eq(JdMatchFormatMember::getFormatId, formatId).one();
        if (one.getPromotionState() != null && one.getPromotionState() > 0) {
            return Success.error("已设置晋级状态");
        }
//            设置晋级生成排名
        one.setPromotionState(state);
        matchFormatMemberService.updateById(one);
//        不到决赛and设置=晋级
        if (arrangeOrder < 3 && state == 1) {
//            晋级到下一个赛程
            JdMatchFormatMember two = new JdMatchFormatMember();
            two.setUserId(one.getUserId());
            final JdMatchFormat format = matchFormatService.lambdaQuery()
                    .eq(JdMatchFormat::getArrangeOrder, arrangeOrder + 1)
                    .eq(JdMatchFormat::getMatchId, matchId).one();
            if (format == null) {
                return Success.error("赛程设置缺失");
            }
            two.setFormatId(format.getId());
            two.setGroupId(one.getGroupId());
            matchFormatMemberService.save(two);
        }
        return Success.success();
    }



    //实时排名api
    @Login
    @PostMapping("/realTimeRanking")
    @ApiOperation("实时排名")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事分类", name = "type", dataType = "integer", required = true),
            @ApiImplicitParam(value = "开始时间", name = "starTime", dataType = "integer"),
            @ApiImplicitParam(value = "结束时间", name = "endTime", dataType = "integer"),
    })
    public Success<Page<List<JdMatchVo>>> realTimeRanking(Integer type,String starTime,String endTime,
                                                    @RequestParam(defaultValue = "1") Integer page,
                                                    @RequestParam(defaultValue = "10") Integer rows){
        starTime = DateUtil.beginOfDay(DateUtil.parseDate(starTime)).toString();
        endTime = DateUtil.endOfDay(DateUtil.parseDate(endTime)).toString();
        List<JdMatchVo> matchVo = matchScoreRecordService.selectMatchVoCount(type,starTime,endTime);
        final Integer total = matchVo.size();
        final Page<List<JdMatchVo>> result = new Page<>(page, rows, total);
        String s = result.convertPage();
        List<JdMatchVo> matchVos = matchScoreRecordService.selectMatchVo(type,starTime,endTime,s);
        result.setTotal(matchVos.size());
        result.setContent(matchVos);
        return Success.success(result);
    }


}
